import os, sys
import json
import numpy as np
import pandas as pd
from typing import List, Dict, Any
from datetime import datetime, timedelta
from mcp.server.fastmcp import FastMCP
import random
import logging
from collections import defaultdict
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../')))
from insight_agent.utils.http_post import get_insight_request, inform_insight_thinking, update_insight_result

# 初始化 MCP 服务器
mcp = FastMCP("ForecastServer")
USER_AGENT = "forecast-app/1.0"

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@mcp.tool()
async def predict_future(
    historical_data: List[Dict[str, Any]],
    periods: int = 5,
    min_value: float = 0.0,
    stability_threshold: float = 0.01
) -> str:
    """
    当用户需要进行数据预测时，请调用该函数。
    该函数接收包含多个日期的时间序列数据，输出指定天数的预测数据。
    参数:
        historical_data: 原始历史数据
        periods: 预测天数
        min_value: 最小值保护
        stability_threshold: 视为"不变"的变化量阈值
    返回:
        预测数据，json格式
    """
    inform_insight_thinking("agent_time_series", f'tools - predict_future')
    if not historical_data or periods <= 0:
        return []
    try:
        # 数据预处理
        df = pd.DataFrame(historical_data)
        df['time'] = pd.to_datetime(df['time'], format='%Y%m%d')
        df = df.sort_values('time')

        # 线性回归拟合
        x = np.arange(len(df))
        y = df['value'].values
        a, b = np.polyfit(x, y, deg=1)
        fitted_values = a * x + b

        # 计算每个点与拟合线的关系
        deviations = y - fitted_values
        df['deviation'] = deviations

        # 计算三态频率和幅度
        up_deltas = []
        down_deltas = []

        for dev in deviations:
            if dev > stability_threshold:
                up_deltas.append(dev)
            elif dev < -stability_threshold:
                down_deltas.append(-dev)  # 存储绝对值

        # 计算三态概率
        total = len(deviations)
        up_prob = len(up_deltas) / total
        down_prob = len(down_deltas) / total
        stable_prob = 1 - up_prob - down_prob

        # 计算平均波动幅度
        avg_up = np.mean(up_deltas) if up_deltas else 0
        avg_down = np.mean(down_deltas) if down_deltas else 0

        # 生成预测
        last_date = df['time'].iloc[-1]
        predictions = []
        original_min = df['value'].min()

        random.seed(42)
        for i in range(1, periods + 1):
            # 基础线性预测
            next_x = len(df) + i - 1
            base_value = a * next_x + b

            # 添加波动
            rand = random.random()
            if rand < up_prob:
                final_value = base_value + avg_up + random.uniform(-avg_up / 2, avg_up / 2)
            elif rand < up_prob + down_prob:
                final_value = base_value - avg_down + random.uniform(-avg_down / 2, avg_down / 2)
            else:
                final_value = base_value


            # 记录预测
            next_date = last_date + timedelta(days=i)
            predictions.append({
                "time": next_date.strftime('%Y%m%d'),
                "value": max(final_value, 0)
            })

        return json.dumps(predictions, ensure_ascii=False)
    except Exception as e:
        logger.error(f"预测失败: {str(e)}", exc_info=True)
        return {"error": f"预测失败: {str(e)}"}



if __name__ == "__main__":
    mcp.run(transport='stdio')